/*
Java source file
Copyright: Umschalt.com 2012
*/
package com.david.documentation.domain.dao.search;

import com.david.documentation.domain.dao.AbstractDAO;
import com.david.documentation.domain.entities.doku.Doku;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.Version;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.jpa.Search;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.List;

@Repository(value = "searchDao")
public class SearchDaoImpl extends AbstractDAO<Doku> implements SearchDao  {

	@PersistenceContext
	private EntityManager entityManager;

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public Class<Doku> getClazz() {
		return Doku.class;
	}

	@Transactional
	public List<Doku> findDokus(String searchTerms, Integer startIndex, Integer maxResults,String[] fieldstoMatch) {
		EntityManager mang = getEntityManager();

		FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(mang);
		QueryParser parser = new MultiFieldQueryParser(Version.LUCENE_30,fieldstoMatch,new StandardAnalyzer(Version.LUCENE_30));
		Query luceneQuery = null;
		try {
			luceneQuery = parser.parse(searchTerms);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		FullTextQuery jpaQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, Doku.class);
		if (startIndex != null && maxResults != null){
			jpaQuery.setFirstResult(startIndex);
			jpaQuery.setMaxResults(maxResults);
		}
		List<Doku> dokus = new ArrayList<Doku>();
		try{
			dokus = jpaQuery.getResultList();
		} catch (Exception e){
			e.printStackTrace();
		}
		System.out.println("SIZE: " + jpaQuery.getResultSize() + "SIZE IM SERVICE: " + dokus.size());
		return dokus;
	}

	@Transactional
	public List<Doku> findDokusByName(String searchTerms, Integer startIndex, Integer maxResults) {
		return findDokus(searchTerms,startIndex,maxResults,new String[]{"name"} );
	}
	@Transactional
	public List<Doku> findDokusByNameAndDescription(String searchTerms, Integer startIndex, Integer maxResults) {
		return findDokus(searchTerms,startIndex,maxResults,new String[]{"name","description"} );
	}
	@Transactional
	public List<String> findDokuNames(String searchTerms, Integer startIndex, Integer maxResults) {
		List<String> names = new ArrayList<String>();
		for (Doku doku : findDokusByNameAndDescription(searchTerms,startIndex,maxResults)){
			if (doku.getName() != null)
				names.add(doku.getName());
		}
		return names;
	}
	@Transactional
	public List<Doku> findDokuNamesSql(String searchTerms) {
		javax.persistence.Query query = getEntityManager().createQuery("from " + getClazz().getSimpleName() + " e where e.name like :aName");
		query.setParameter("aName", "%" + searchTerms + "%");
        return query.getResultList();
	}
	@Transactional
	public List<Doku> findDokuNamesSqlLimit(String searchterm, Integer startIndex, Integer maxResults) {
		javax.persistence.Query query = getEntityManager().createQuery("from " + getClazz().getSimpleName() + " e WHERE e.name LIKE :aName");
        query.setParameter("aName", "%" + searchterm + "%");
		query.setFirstResult(startIndex);
		query.setMaxResults(maxResults);
        return query.getResultList();
	}

	@Transactional
	public List<Doku> findDokuNamesAndDescriptionSql(String searchTerms) {
		javax.persistence.Query query = getEntityManager().createQuery("from " + getClazz().getSimpleName() + " e where e.name like :aName or e.description like :aName");
        query.setParameter("aName", "%" + searchTerms + "%");
        return query.getResultList();
	}

	@Transactional
	public List<Doku> findDokuNamesAndDescriptionSqlLimit(String searchterm, Integer startIndex, Integer maxResults) {
		javax.persistence.Query query = getEntityManager().createQuery("from " + getClazz().getSimpleName() + " e WHERE e.name LIKE :aName or e.description like :aName");
        query.setParameter("aName", "%" + searchterm + "%");
		query.setFirstResult(startIndex);
		query.setMaxResults(maxResults);
        return query.getResultList();
	}

}
